
#include "meshAnimator.h"

MeshAnimator::MeshAnimator() 
   :Animator() {
   
   mesh = 0;
}

MeshAnimator::MeshAnimator(Mesh *model, Skeleton *skeleton, Motion *motion)
   :Animator(skeleton, motion) {
   
   mesh = model;
   setting();
}

void MeshAnimator::setting() {
   
   assert(mesh != 0);
   assert(skeleton != 0);
   
   ipositions.resize(mesh->nvertices());
   inormals.resize(mesh->nvertices());
   Vertex_iterator vi = mesh->vertices_begin();
   for (unsigned int i=0; i<ipositions.size(); ++i, ++vi) {
      ipositions[i] = vi->point();
      inormals[i] = vi->normal();
   }
}

void MeshAnimator::frame(int f) {
   
   /// Animate the skeleton
   Animator::frame(f);
   
   /// animate the mesh: method 1
   int i = 0;
   Vertex_iterator vi = mesh->vertices_begin();
   while (vi != mesh->vertices_end()) {
      Quat Q(0,0,0,0); Vector3 t(0,0,0); Number s=0.0;
      for (int j=0; j<vi->weights.size(); ++j) {
         const Number &w = vi->weights[j];
         if (w == 0) continue;
         Q = Q + w*skeleton->getBoneQuaternion(j);
         t = t + w*skeleton->getBoneTranslation0(j);
         if (w == 1) break;
      }
      
      //~ /// normalize the quaternion Q???
      Number l = length(Q);
      Q = Q*(1.0/l);
      
      const Point3 &Po = ipositions[i]; // the original vertex position
      Quat qPo(Po[0],Po[1],Po[2]);
      Quat qp = Q*qPo*conjugate(Q);
      Point3 &P = vi->point();
      P = Point3(qp[1],qp[2],qp[3]) + t; // the deformed vertex position
      
      const Vector3 &No = inormals[i]; // the original vertex normal
      Quat qNo(No[0],No[1],No[2]);
      Quat qn = Q*qNo*conjugate(Q);
      Vector3 &N = vi->normal();
      N = Vector3(qn[1],qn[2],qn[3]); // the deformed vertex normal
      
      ++vi; ++i;
   }
   
   /*
   /// Animate the mesh: method 2
   int i = 0;
   Vertex_iterator vi = mesh->vertices_begin();
   while (vi != mesh->vertices_end()) {
      Quat Q(0,0,0,0); Vector3 t(0,0,0); Number s=0.0;
      for (int j=0; j<vi->weights.size(); ++j) {
         const Number &w = vi->weights[j];
         if (w == 0) continue;
         Q = Q + w*skeleton->getBoneQuaternion(j);
         const Vector3 &t0 = skeleton->getBoneTranslation0(j);
         const Vector3 &t1 = skeleton->getBoneTranslation1(j);
         const Number &s0 = skeleton->getBoneScale0(j);
         const Number &s1 = skeleton->getBoneScale1(j);
         Vector3 tt = t0*(vi->ts[j]) + t1*(1.0-vi->ts[j]);
         Number ss = s0*(vi->ts[j]) + s1*(1.0-vi->ts[j]);
         t = t + w*tt;
         s = s + w*ss;
      }
      
      Vector3 vQ(Q[1],Q[2],Q[2]);
      Vector3 tv = t*Q[0] - vQ*s + cross_product(vQ, t);
      
      const Point3 &Po = ipositions[i]; // the original vertex position
      Quat qPo(Po[0],Po[1],Po[2]);
      Quat qp = Q*qPo*conjugate(Q);
      Point3 &P = vi->point();
      P = Point3(qp[1],qp[2],qp[3]) + tv; // the deformed vertex position
      
      ++vi; ++i;
   }*/
}
